//------------------------------------------------------------------------------
//SFWK Framework
//Copyright (C) 2011 SQLI

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.IO;
using System.Xml.Serialization;
using SFWK.Core.Linq;
namespace SFWK.Core.ExpressionBuilder
{
    /// <summary>
    /// Helper based on codeplex metalinq project to serialize/Deserialize lambda expressions to string
    /// http://metalinq.codeplex.com/releases/view/23951
    /// http://reverseblade.blogspot.com/2008/11/how-to-serialize-lambda-expressions.html
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public static class ExpressionSerializerHelper<TEntity> where TEntity:class
    {
        #region Expression<Func<TEntity, bool>>
        /// <summary>
        /// Serialize a lambda expression
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static string Serialize(Expression<Func<TEntity, bool>> expression)
        {
            var editableExpression = SFWK.Core.ExpressionBuilder.EditableExpression.CreateEditableExpression(expression.PartialEval());

            var sw = new StringWriter();
            new XmlSerializer(typeof(EditableLambdaExpression)).Serialize(sw, editableExpression);
            return sw.ToString();
        }

        /// <summary>
        /// DeSerialize a lambda expression from string
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static Expression<Func<TEntity, bool>> Deserialize(string expression)
        {
            // Deserialize it
            EditableExpression editableExpression = new XmlSerializer(typeof(EditableLambdaExpression)).Deserialize(new StringReader(expression)) as EditableExpression;

            // Convert it to lambda expresion
            if (editableExpression != null)
                return editableExpression.ToExpression() as Expression<Func<TEntity, bool>>;
            else
                return null;
        }
        #endregion Expression<Func<TEntity, bool>>

        
        public static string SerializeOrderBy(Expression<Func<IQueryable<TEntity>, IOrderedQueryable>> expression)
        {
            var editableExpression = SFWK.Core.ExpressionBuilder.EditableExpression.CreateEditableExpression(expression.PartialEval());

            var sw = new StringWriter();
            new XmlSerializer(typeof(EditableLambdaExpression)).Serialize(sw, editableExpression);
            return sw.ToString();
        }

        /// <summary>
        /// DeSerialize a lambda expression from string
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static Expression<Func<IQueryable<TEntity>, IOrderedQueryable>> DeserializeOrderBy(string expression)
        {
            // Deserialize it
            EditableExpression editableExpression = new XmlSerializer(typeof(EditableLambdaExpression)).Deserialize(new StringReader(expression)) as EditableExpression;

            // Convert it to lambda expresion
            if (editableExpression != null)
                return editableExpression.ToExpression() as Expression<Func<IQueryable<TEntity>, IOrderedQueryable>>;
            else
                return null;
        }



    }
}

